#include <common.h>
#include "syscall.h"
#include "fs.h"

static void SYS_YIELD(){
#ifdef CONFIG_STRACE
	Log("strace: SYS_YIELD");
#endif
	printf("yield happened\n");
}
static void SYS_EXIT(){
#ifdef CONFIG_STRACE
	Log("strace: SYS_EXIT");
#endif
	printf("exit happened\n");
	halt(0);
}
static void SYS_WRITE(Context *c){
	int fd = c->GPR2;
	char*buf = (char*)c->GPR3;
	int len = c->GPR4;	
	c->GPRx = fs_write(fd,buf,len);
#ifdef CONFIG_STRACE
	Log("strace: SYS_WRITE file=%s ,buf=%d ,len=%d ,return=%d",get_file_name(fd),buf,len,c->GPRx);
#endif
}
static void SYS_SBRK(Context *c){
	c->GPRx =0 ;
#ifdef CONFIG_STRACE
	Log("strace: SYS_SBRK ,program break=%d ,increment=%d ,return=%d",c->GPR2,c->GPR3,c->GPRx);
#endif
}
static void SYS_OPEN(Context *c){
	int ret = fs_open((char*)c->GPR2,c->GPR3,c->GPR4);	
#ifdef CONFIG_STRACE
	Log("strace: SYS_OPEN file=%s ,flags=%d ,mode=%d .return=%d",c->GPR2,c->GPR3,c->GPR4,ret);
#endif
	c->GPRx = ret;
}
static void SYS_CLOSE(Context *c){
	c->GPRx = fs_close(c->GPR2);
#ifdef CONFIG_STRACE
	Log("strace: SYS_CLOSE file=%s ,result=%d",get_file_name(c->GPR2),c->GPRx);
#endif
}
static void SYS_LSEEK(Context *c){
	size_t ret=fs_lseek(c->GPR2,c->GPR3,c->GPR4);
#ifdef CONFIG_STRACE
	Log("strace: SYS_LSEEK file=%s ,offset=%d ,whence=%d ,result=%d",get_file_name(c->GPR2),c->GPR3,c->GPR4,ret);
#endif
	c->GPRx = ret;
}
static void SYS_READ(Context *c){
	size_t ret = fs_read(c->GPR2,(void*)c->GPR3,c->GPR4);
#ifdef CONFIG_STRACE
	Log("strace: SYS_READ file=%s ,buf=%d ,count=%d ,result=%d",get_file_name(c->GPR2),c->GPR3,c->GPR4,ret);
#endif
	c->GPRx = ret;
}


static void SYS_GETTIMEOFDAY(Context *c){
	size_t us = io_read(AM_TIMER_UPTIME).us;	
	size_t ret = us;
#ifdef CONFIG_STRACE
	Log("strace: SYS_GETTIMEOFDAY ,us=%d ,result=%d",us,ret);
#endif
	c->GPRx = ret;
}
void do_syscall(Context *c) {
  uintptr_t a[4];
	a[0] = c->GPR1;
	a[1] = c->GPR2;
	a[2] = c->GPR3;
	a[3] = c->GPR4;
	//printf("a0=%d,a1=%d,a2=%d,a3=%d\n",a[0],a[1],a[2],a[3]);
  switch (a[0]) {
		case SYS_yield:SYS_YIELD();break;
		case SYS_exit:SYS_EXIT();break;
		case SYS_write:SYS_WRITE(c);break;
		case SYS_brk:SYS_SBRK(c);break;
		case SYS_open:SYS_OPEN(c);break;
		case SYS_lseek:SYS_LSEEK(c);break;
		case SYS_read:SYS_READ(c);break;
	  case SYS_close:SYS_CLOSE(c);break;
		case SYS_gettimeofday:SYS_GETTIMEOFDAY(c);break;
    default: panic("Unhandled syscall ID = %d", a[0]);
  }
}

